package de.m3soft.bazinga;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;

/**
 * Swing-component for input and output of numeric values.
 */

public class JNumberField extends JTextField {

	/**
	 * 
	 */
	private static final long serialVersionUID = -6555427593695958093L;

	/** constructor for a JNumberField */
	public JNumberField() {
		enableEvents(AWTEvent.KEY_EVENT_MASK);
	}

	/** Gets a double-value from the JNumberField. */
	public double getDouble() {
		Double d = new Double(getText());
		return d.doubleValue();
	}

	/** Gets a float-value from the JNumberField. */
	public float getFloat() {
		Double d = new Double(getText());
		return d.floatValue();
	}

	/** Gets an int-value from the JNumberField. */
	public int getInt() {
		Double d = new Double(getText());
		return d.intValue();
	}

	/** Gets a long-value from the JNumberField. */
	public long getLong() {
		Double d = new Double(getText());
		return d.longValue();
	}

	/** Checks wether the JNumberField contains a valid numeric value. */
	public boolean isNumeric() {
		final String Digits = "(\\p{Digit}+)";
		final String HexDigits = "(\\p{XDigit}+)";
		// an exponent is 'e' or 'E' followed by an optionally
		// signed decimal integer.
		final String Exp = "[eE][+-]?" + Digits;
		final String fpRegex = ("[\\x00-\\x20]*" + // Optional leading "whitespace"
		"[+-]?(" + // Optional sign character
		"NaN|" + // "NaN" string
		"Infinity|" + // "Infinity" string

		// A decimal floating-point string representing a finite positive
		// number without a leading sign has at most five basic pieces:
		// Digits . Digits ExponentPart FloatTypeSuffix
		//
		// Since this method allows integer-only strings as input
		// in addition to strings of floating-point literals, the
		// two sub-patterns below are simplifications of the grammar
		// productions from the Java Language Specification, 2nd
		// edition, section 3.10.2.

		// Digits ._opt Digits_opt ExponentPart_opt FloatTypeSuffix_opt
		"(((" + Digits + "(\\.)?(" + Digits + "?)(" + Exp + ")?)|" +

		// . Digits ExponentPart_opt FloatTypeSuffix_opt
		"(\\.(" + Digits + ")(" + Exp + ")?)|" +

		// Hexadecimal strings
		"((" +
		// 0[xX] HexDigits ._opt BinaryExponent FloatTypeSuffix_opt
		"(0[xX]" + HexDigits + "(\\.)?)|" +

		// 0[xX] HexDigits_opt . HexDigits BinaryExponent FloatTypeSuffix_opt
		"(0[xX]" + HexDigits + "?(\\.)" + HexDigits + ")" +

		")[pP][+-]?" + Digits + "))" + "[fFdD]?))" + "[\\x00-\\x20]*");// Optional trailing "whitespace"

		return java.util.regex.Pattern.matches(fpRegex, getText());
	}

	/** Sets a double-value into the JNumberField. */
	public void setDouble(double d) {
		setText(String.valueOf(d));
	}

	/** Sets a double-value with N digits into the JNumberField. */
	public void setDouble(double d, int N) {
		setText(String.format(Locale.ENGLISH, "%." + N + "f", d));
	}

	/** Sets a float-value into the JNumberField. */
	public void setFloat(float f) {
		setText(String.valueOf(f));
	}

	/** Sets a float-value with N digits into the JNumberField. */
	public void setFloat(float f, int N) {
		setText(String.format(Locale.ENGLISH, "%." + N + "f", f));
	}

	/** Sets an int-value into the JNumberField. */
	public void setInt(int i) {
		setText(String.valueOf(i));
	}

	/** Sets a long-value into the JNumberField. */
	public void setLong(long l) {
		setText(String.valueOf(l));
	}

	/** Clears the JNumberField */
	public void clear() {
		setText("");
	}

	protected void processKeyEvent(KeyEvent e) {
		super.processKeyEvent(e);
		if (isNumeric() || getText().equals("-") || getText().equals("") || getText().equals("."))
			setBackground(Color.white);
		else
			setBackground(Color.red);
	}

}